package com.onefish.toolkit.netty.file;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.io.RandomAccessFile;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyNettyClientHandler extends SimpleChannelInboundHandler {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private int readLength;
    private int start = 0;
    private int lastLength = 0;
    public RandomAccessFile randomAccessFile;
    private MySendFile sendFile;


    public MyNettyClientHandler(MySendFile ef) {
        this.sendFile = ef;
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        System.out.println(nowTime() + " 【客户端】 关闭与服务端-" + SocketAddress(ctx.channel()) + " 的socket连接");
    }

    public void channelActive(ChannelHandlerContext ctx) {
        try {
            randomAccessFile = new RandomAccessFile(sendFile.getFile(), "r");
            randomAccessFile.seek(sendFile.getStart());
            lastLength = 1024 * 1024;
            //一次读取1MB
            byte[] bytes = new byte[lastLength];
            if ((readLength = randomAccessFile.read(bytes)) != -1) {
                sendFile.setEnd(readLength);
                sendFile.setBytes(bytes);
                ctx.writeAndFlush(sendFile);
            } else {
                System.out.println(nowTime() + " 【客户端】没有读取到文件内容->" + sendFile.getFileName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof Integer) {
            start = (Integer) msg;
            //是否读完文件，到达文件末尾
            if (start != -1) {
                randomAccessFile = new RandomAccessFile(sendFile.getFile(), "r");
                //移到文件指针到指定位置
                randomAccessFile.seek(start);
                //剩余待读取文件的内容长度
                int length = (int) (randomAccessFile.length() - start);
                if (length < lastLength) {
                    lastLength = length;
                }
                byte[] bytes = new byte[lastLength];
                if ((readLength = randomAccessFile.read(bytes)) != -1 && (randomAccessFile.length() - start) > 0) {
                    sendFile.setEnd(readLength);
                    sendFile.setBytes(bytes);
                    try {
                        System.out.println(nowTime() + " 【客户端】 向服务端-" + SocketAddress(ctx.channel()) + " 发送文件->" + sendFile.getFileName() + "，此次字节数：" + readLength);
                        ctx.writeAndFlush(sendFile);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    randomAccessFile.close();
                    ctx.close();
                    System.out.println(nowTime() + " 【客户端】 向服务端-" + SocketAddress(ctx.channel()) + "  发送本地文件-" + sendFile.getFileName() + " 发送完毕，文件总大小：" + formatFileSize(start));
                }
            }
        }
    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    public static String SocketAddress(Channel channel) {
        try {
            if (channel == null || channel.remoteAddress() == null) {
                System.out.println("地址为空");
                return "地址为空";
            }
            return channel.remoteAddress().toString().replace("/", "");
        } catch (Exception e) {
            e.printStackTrace();
            return "地址获取异常";
        }
    }

    public static String nowTime() {
        try {
            return sdf.format(new Date());
        } catch (Exception e) {
            e.printStackTrace();
            return "1970-01-01 00:00:00";
        }
    }

    public static String formatFileSize(long size) {
        if (size <= 0) {
            return "0B";
        }
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.###").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }
}
